#ifndef CLIENT_H
#define CLIENT_H

#include <iostream>
#include<nlohmann/json.hpp>
#include <cstring>
#include<string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<thread>




#include"MsgType.h"
#define UNKNOWN 0 //未知请求
#define LOGIN 1    //登录
#define CREAT_USER 2 //创建用户
#define JOIN_CHANNEL 3 //加入通道
#define CREATE_CHANNEL 4 //创建通道
#define SEND_MSG 5 //向对应通道添加信息
#define GET_CHANNEL_INFO 6 //请求获取通道内信息
#define INVITE_USER 7 //邀请加入通道
#define AGREE_JOIN_CHANNEL 8//同意加入
#define DISAGREE_JOIN_CHANNEL 9 //拒绝加入
#define LOGOUT 10 //退出请求
#define DEL_CHANNEL 11 //删除通道请求
#define EXIT_CHANNEL 12 //退出通道请求
#define GET_CHANNEL_LIST 13 //获取通道列表请求
#define GET_NEWER_MSG 14 //获取最新信息请求


// #define SEND_AND_RECE=0;


#define ERROR_INFO 100 //错误信息请求
//server_ip为服务器IP地址，server_port为服务器端口号
#define PORT 6666
#define IP  "192.168.227.128"

using namespace std;

class TcpClient {
    using json = nlohmann::json;
    private:
        int sockfd;
        struct sockaddr_in server_addr;
    
    public:
        TcpClient(const std::string& server_ip, int server_port) {
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) {
                perror("Error opening socket");
                exit(1);
            }
    
            memset(&server_addr, 0, sizeof(server_addr));
            server_addr.sin_family = AF_INET;
            server_addr.sin_port = htons(server_port);
    
            if (inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr) <= 0) {
                perror("Invalid address/ Address not supported");
                exit(1);
            }
        }
    
        ~TcpClient() {
            close(sockfd);
        }
        
        std::string get_current_time() {
            // 获取当前时间点
            auto now = std::chrono::system_clock::now();
            // 转换为 time_t 类型
            auto time_t_now = std::chrono::system_clock::to_time_t(now);
            // 转换为本地时间
            std::tm local_time = *std::localtime(&time_t_now);
        
            // 使用字符串流格式化时间
            std::ostringstream oss;
            oss << std::put_time(&local_time, "%Y-%m-%d %H:%M:%S");
            return oss.str();
        }
    
        void connect_to_server() {
            if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
                perror("Connection Failed");
                exit(1);
            }
        }
    
        void send_message(const std::string& message) {
            if (send(sockfd, message.c_str(), message.length(), 0) < 0) {
                perror("Send failed");
                exit(1);
            }
        }
    
        std::string receive_message(int buffer_size = 4096) {
            char buffer[buffer_size] = {0};

            string read_buf;

            ssize_t bytes_read;
            while((bytes_read = recv(sockfd, buffer, buffer_size, 0)) > 0){
                read_buf.append(buffer, bytes_read);
            }

            if(bytes_read == 0){
                cout << "Server closed connection\n" << endl;
                exit(0);
            }
            else if(bytes_read < 0){
                perror("Msg receive completed\n");
            }
            return read_buf;
        }

        void send_login_request(const int& user_id, const std::string& pwd) {
            json request_json;
            request_json["request_type"] = LOGIN;
            request_json["user_id"] = user_id;
            request_json["pwd"] = pwd;
            std::string request_str = request_json.dump();
            send_message(request_str);

            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        int send_create_user_request(const std::string& name, const std::string& pwd) {
            json request_json;
            request_json["request_type"] = CREAT_USER;
            request_json["name"] = name;
            request_json["pwd"] = pwd;
            std::string request_str = request_json.dump();
            send_message(request_str);
            
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            return response_json["id"].get<int>();
            #endif

            return -1;
        }

        void send_logout_request(const int& user_id) {
            json request_json;
            request_json["request_type"] = LOGOUT;
            request_json["user_id"] = user_id;
           string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            string response_str = receive_message();
            json response_json = json::parse(response_str);
            cout<<response_json.dump(4)<<endl;
            #endif
        }

        void send_get_chat_list_request(const int& user_id) {
            json request_json;
            request_json["request_type"] = GET_CHANNEL_LIST;
            request_json["user_id"] = user_id;
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        string send_create_chat_request(const int& user_id, const std::string& chat_name) {
            json request_json;
            request_json["request_type"] = CREATE_CHANNEL;
            request_json["user_id"] = user_id;
            request_json ["chat_room_name"] = chat_name;
            string request_str = request_json.dump();
            cout<<request_str<<endl;
            send_message(request_str);

            #ifdef SEND_AND_RECE
            string response_str = receive_message();
            json response_json = json::parse(response_str);
            cout<<response_json.dump(4)<<endl;
            return response_json["chat_room_id"].get<string>();
            #endif
            return "";
        }

        void send_join_chat_request(const int& user_id, const std::string& chat_id) {
            json request_json;
            request_json["request_type"] = JOIN_CHANNEL;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        void send_exit_chat_request(const int& user_id, const std::string& chat_id) {
            json request_json;
            request_json["request_type"] = EXIT_CHANNEL;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        void send_del_chat_request(const int& user_id, const std::string& chat_id) {
            json request_json;
            request_json["request_type"] = DEL_CHANNEL;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }
        
        void send_get_chat_info_request(const int& user_id, const std::string& chat_id) {
            json request_json;
            request_json["request_type"] = GET_CHANNEL_INFO;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        void send_send_msg_request(const int& user_id, const std::string& chat_id, const std::string& msg) {
            string time;
            time = get_current_time();

            Msg new_msg(user_id, chat_id,time,msg,MsgType::characters);
            json request_json;
            request_json["request_type"] = SEND_MSG;
            request_json["Msg"]=new_msg.serializeMsg();
            string request_str=request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            string response_str = receive_message();
            json response_json = json::parse(response_str);
            cout<<response_json.dump(4)<<endl;
            #endif
        }

        void send_get_newer_msg_request(const int& user_id, const std::string& chat_id, const int& msg_num) {
            json request_json;
            request_json["request_type"] = GET_NEWER_MSG;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            request_json["msg_num"]=msg_num;
            string request_str=request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            string response_str = receive_message();
            json response_json = json::parse(response_str);
            cout<<response_json.dump(4)<<endl;
            #endif
        }

        void send_invite_user_request(const int& user_id, const std::string& chat_id, const int& invite_user_id) {
            json request_json;
            request_json["request_type"] = INVITE_USER;
            request_json["user_id"] = user_id;
            request_json["chat_room_id"] = chat_id;
            request_json["invite_user_id"] = invite_user_id;
            request_json["time"] = get_current_time();
            request_json["content"]="邀请你加入";
            std::string request_str = request_json.dump();
            send_message(request_str);
            #ifdef SEND_AND_RECE
            std::string response_str = receive_message();
            json response_json = json::parse(response_str);
            std::cout<<response_json.dump(4)<<std::endl;
            #endif
        }

        void rece_from_server() {
            while(1){
                string response_str = receive_message();
                json response_json = json::parse(response_str);
                cout<<"receive from server:"<<endl;
                cout<<response_json.dump(4)<<endl;
            }
        }

    };
#endif /* CLIENT_H */